import axios, { type AxiosInstance, type AxiosRequestConfig, type AxiosResponse } from 'axios'
import { ElMessage, ElMessageBox } from 'element-plus'
import { useAuthStore } from '@/stores/auth'
import router from '@/router'

// 创建axios实例
const http: AxiosInstance = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL || '/api',
  timeout: 30000,
  headers: {
    'Content-Type': 'application/json'
  }
})

// 请求拦截器
http.interceptors.request.use(
  (config: AxiosRequestConfig) => {
    // 添加认证Token
    const authStore = useAuthStore()
    if (authStore.token) {
      config.headers = config.headers || {}
      config.headers.Authorization = `Bearer ${authStore.token}`
    }

    // 添加租户ID
    const tenantId = localStorage.getItem('tenantId')
    if (tenantId) {
      config.headers = config.headers || {}
      config.headers['X-Tenant-Id'] = tenantId
    }

    // 添加请求ID
    config.headers = config.headers || {}
    config.headers['X-Request-Id'] = generateRequestId()

    return config
  },
  (error) => {
    console.error('请求拦截器错误:', error)
    return Promise.reject(error)
  }
)

// 响应拦截器
http.interceptors.response.use(
  (response: AxiosResponse) => {
    const { data, config } = response

    // 处理业务状态码
    if (data.code !== undefined && data.code !== 200) {
      const message = data.message || '请求失败'

      // 特殊状态码处理
      if (data.code === 401) {
        handleUnauthorized()
        return Promise.reject(new Error(message))
      }

      if (data.code === 403) {
        handleForbidden()
        return Promise.reject(new Error(message))
      }

      ElMessage.error(message)
      return Promise.reject(new Error(message))
    }

    return data
  },
  async (error) => {
    const { response, config } = error

    if (!response) {
      ElMessage.error('网络错误，请检查网络连接')
      return Promise.reject(error)
    }

    const { status, data } = response
    const message = data?.message || getErrorMessage(status)

    switch (status) {
      case 401:
        await handleUnauthorized()
        break
      case 403:
        handleForbidden()
        break
      case 404:
        ElMessage.error('请求的资源不存在')
        break
      case 422:
        handleValidationError(data?.errors)
        break
      case 429:
        ElMessage.warning('请求过于频繁，请稍后再试')
        break
      case 500:
        ElMessage.error('服务器内部错误')
        break
      case 502:
      case 503:
      case 504:
        ElMessage.error('服务暂时不可用，请稍后再试')
        break
      default:
        ElMessage.error(message)
        break
    }

    return Promise.reject(error)
  }
)

// 处理未认证
async function handleUnauthorized() {
  const authStore = useAuthStore()

  // 如果有刷新Token，尝试刷新
  if (authStore.refreshToken) {
    try {
      await authStore.refreshAccessToken()
      return
    } catch (error) {
      console.error('刷新Token失败:', error)
    }
  }

  // 清除认证信息并跳转到登录页
  authStore.logout()
}

// 处理禁止访问
function handleForbidden() {
  ElMessage.error('您没有权限访问此资源')
  router.push({ name: 'Forbidden' })
}

// 处理验证错误
function handleValidationError(errors: Record<string, string[]>) {
  if (!errors) return

  const errorMessages = Object.values(errors).flat()
  if (errorMessages.length > 0) {
    ElMessage.error(errorMessages[0])
  }
}

// 获取错误消息
function getErrorMessage(status: number): string {
  const errorMessages: Record<number, string> = {
    400: '请求参数错误',
    401: '未认证或认证已过期',
    403: '权限不足',
    404: '请求的资源不存在',
    405: '请求方法不被允许',
    408: '请求超时',
    409: '请求冲突',
    422: '请求参数验证失败',
    429: '请求过于频繁',
    500: '服务器内部错误',
    502: '网关错误',
    503: '服务暂时不可用',
    504: '网关超时'
  }

  return errorMessages[status] || '未知错误'
}

// 生成请求ID
function generateRequestId(): string {
  return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
}

// 请求方法类型
export interface RequestConfig extends AxiosRequestConfig {
  loading?: boolean
  errorMessage?: boolean
  successMessage?: boolean
}

// 扩展http方法
http.get = function<T = any>(url: string, config: RequestConfig = {}) {
  return http.get<T>(url, config)
}

http.post = function<T = any>(url: string, data?: any, config: RequestConfig = {}) {
  return http.post<T>(url, data, config)
}

http.put = function<T = any>(url: string, data?: any, config: RequestConfig = {}) {
  return http.put<T>(url, data, config)
}

http.delete = function<T = any>(url: string, config: RequestConfig = {}) {
  return http.delete<T>(url, config)
}

export default http